use crate::config::Operation;
use anyhow::Result;
use async_net::TcpStream;
use futures_lite::future;
use http_types::{Body, Method, Request, Url};

mod config;

fn main() -> Result<()> {
    // pretty_env_logger::init_timed();
    future::block_on(run())?;
    Ok(())
}

async fn run() -> Result<()> {
    let cfg = config::init().await?;

    let (method, body) = match &cfg.operation {
        Operation::QUERY => (
            Method::Post,
            Body::from_json(&cfg.args).map_err(|e| anyhow::anyhow!(e))?,
        ),
        Operation::DANGEROUS => (
            Method::Put,
            Body::from_json(&cfg.args).map_err(|e| anyhow::anyhow!(e))?,
        ),
        Operation::UPLOAD => (Method::Put, Body::from_file(&cfg.args.file).await?),
    };

    let url = Url::parse(&cfg.proxy)?.join((&cfg.operation).as_ref())?;
    let mut req = Request::new(method, url);
    req.set_body(body);

    let addr = req
        .url()
        .socket_addrs(|| match req.url().scheme() {
            "http" => Some(80),
            "https" => Some(443),
            _ => None,
        })?
        .into_iter()
        .next()
        .ok_or_else(|| anyhow::anyhow!("Invalid proxy address: {}", &cfg.proxy))?;

    let stream = TcpStream::connect(addr).await?;
    let res = async_h1::connect(stream, req)
        .await
        .map_err(|e| anyhow::anyhow!(e))?
        .body_string()
        .await
        .map_err(|e| anyhow::anyhow!(e))?;

    async_fs::write("res.txt", res).await?;
    Ok(())
}
